package cn.edu.gduf.luowowo.member.service.impl;

import cn.edu.gduf.luowowo.cache.service.IUserInfoRedisService;
import cn.edu.gduf.luowowo.common.exception.LogicException;
import cn.edu.gduf.luowowo.common.util.Assert;
import cn.edu.gduf.luowowo.common.util.Consts;
import cn.edu.gduf.luowowo.common.util.RedisKeys;
import cn.edu.gduf.luowowo.member.domain.UserInfo;
import cn.edu.gduf.luowowo.member.mapper.UserInfoMapper;
import cn.edu.gduf.luowowo.member.service.IUserInfoService;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;

@Service
public class UserInfoServiceImpl implements IUserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Reference
    private IUserInfoRedisService userInfoRedisService;

    @Override
    public UserInfo get(Long id) {
        return userInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public boolean checkPhone(String phone) {
        int count = userInfoMapper.selectByPhone(phone);
        return count > 0;
    }

    @Override
    public void sendVerifyCode(String phone) throws LogicException {
        // 判断2分中内是否发送过短信(控制短信验证码的发送频率)
        userInfoRedisService.isSendVerifyCode(RedisKeys.VERIFY_CODE_TIME.join(phone));

        // 生成验证码
        String code = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 4);

        // 发送短信  TODO:可以发送短信，但是我的账号被禁用了
        System.out.println("您的短信验证码为 " + code + " 请在" + Consts.VERIY_CODE_VALID_TIME + "分钟内使用");
        StringBuilder message = new StringBuilder();
        message.append("http://utf8.api.smschinese.cn/?").append("Uid=").append("龙洞刘德华").
                append("&Key=").append("d41d8cd98f00b204e980").append("&smsMob=").
                append(phone).append("&smsText=验证码：").append(code);
        // 使用java代码发送请求
        RestTemplate restTemplate = new RestTemplate();
        String object = restTemplate.getForObject(message.toString(), String.class);
        System.out.println(object); //返回的信息是一个状态码

        // 保存验证码的信息，加到缓存中
        userInfoRedisService.addValueToRedis(RedisKeys.VERIFY_CODE.join(phone), code, RedisKeys.VERIFY_CODE.getTime());

        // 保存短信发送的频率。这里把phone作为value存进去没什么意义，只是不知道放什么好
        userInfoRedisService.addValueToRedis(RedisKeys.VERIFY_CODE_TIME.join(phone), phone, RedisKeys.VERIFY_CODE_TIME.getTime());
    }

    @Override
    public void register(String phone, String nickname, String password, String rpassword, String verifyCode) throws LogicException {
        // 判断参数是否为空
        Assert.hasLength(phone, "手机号码不能为空");
        Assert.hasLength(nickname, "昵称不能为空");
        Assert.hasLength(password, "密码设置不能为空");
        Assert.hasLength(rpassword, "确认密码不能为空");
        Assert.hasLength(verifyCode, "请输入验证码");

        // 判断手机号格式是否正确 ^1[3456789]\d{9}$
        String regex = "^((13[0-9])|(14[5-7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\\d{8}$";
        boolean matches = Pattern.compile(regex).matcher(phone).matches();
        if (!matches) {
            throw new LogicException("手机号码格式不正确");
        }
        // 判断手机号是否唯一
        if (checkPhone(phone)) {
            throw new LogicException("该手机号码已被注册");
        }

        // 判断两次密码是否一致
        Assert.equalsPasswords(password, rpassword);

        // 判断验证码是否正确，从缓存中拿，调用缓存服务的方法
        userInfoRedisService.equalsVerifyCode(RedisKeys.VERIFY_CODE.join(phone), verifyCode);

        // 注册
        UserInfo userInfo = new UserInfo();
        userInfo.setNickname(nickname);
        userInfo.setPhone(phone);
        userInfo.setPassword(password);
        userInfo.setHeadImgUrl("/images/default.jpg");
        userInfo.setState(UserInfo.STATE_NORMAL);
        userInfoMapper.insert(userInfo);
    }

    @Override
    public String userLogin(String username, String password) throws LogicException {
        //判断参数是否为空
        Assert.hasLength(username, "用户名不能为空");
        Assert.hasLength(password, "密码不能为空");

        //查询是否存在对应的用户
        UserInfo user = userInfoMapper.selectByUsernameAndPassword(username, password);
        if (user == null) {
            throw new LogicException("账号或密码错误");
        }
        //生成一个唯一的token
        String token = UUID.randomUUID().toString().replaceAll("-", "");

        //把user对象信息存储到redis缓存数据库中
        userInfoRedisService.addTokenToRedis(RedisKeys.USER_TOKEN.join(token), user, RedisKeys.USER_TOKEN.getTime());

        //返回token
        return token;
    }

    @Override
    public String updateUserLogin(UserInfo u) {
        //生成一个唯一的token
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //把user对象信息存储到redis缓存数据库中
        userInfoRedisService.addTokenToRedis(RedisKeys.USER_TOKEN.join(token), u, RedisKeys.USER_TOKEN.getTime());
        //返回token
        return token;
    }

    @Override
    public List<UserInfo> list() {
        return userInfoMapper.selectAll();
    }

    @Override
    public int getCountForConcern(Long id) {
        return userInfoMapper.selectCountForConcern(id);
    }

    @Override
    public int getCountForFans(Long id) {
        return userInfoMapper.selectCountForFans(id);
    }

    @Override
    public List<Long> getConcernId(Long id) {
        return userInfoMapper.selectConcernId(id);
    }

    @Override
    public List<UserInfo> queryConcernByIds(List<Long> arry) {

        return userInfoMapper.selectConcernByIds(arry);
    }

    @Override
    public int getCountForCoins(Long id) {
        return userInfoMapper.getCountForCoins(id);
    }

    @Override
    public void updateById(UserInfo user) {
        userInfoMapper.updateByPrimaryKey(user);
    }

    @Override
    public void updateHearderById(String headImg, Long id) {
        userInfoMapper.updateHeadImg(headImg, id);
    }

    @Override
    public void update(UserInfo userInfo) {
        userInfoMapper.updateByPrimaryKey(userInfo);
        /*String token = UUID.randomUUID().toString();
        token = RedisKeys.USER_TOKEN.join(token);
        userInfoRedisService.addValueToRedis(token, JSON.toJSONString(userInfo),RedisKeys.USER_TOKEN.getTime());*/

    }

    @Override
    public void focus(Long id, Long uid) {
        userInfoMapper.focus(id, uid);
    }

    @Override
    public UserInfo selectByPrimaryKey(Long id) {
        return userInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public void updatePhone(String phone, String newMobile) {
        List<String> allPhone = userInfoMapper.getAllPhone();
        if (allPhone.contains(newMobile)){
            throw new LogicException("我丢手机号已被绑定");
        }
        userInfoMapper.updatePhone(phone,newMobile);
    }
}
